#ifndef ITGOP_PATCHER_OPTIONS_H_INCLUDED_
#define ITGOP_PATCHER_OPTIONS_H_INCLUDED_

#include "lhcutils/StartupEnvironment.h"
#include "lhcutils/ITextWriter.h"
#include "lhcutils/UnicodeString.h"
#include <vector>
#include <string>
#include <iostream>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/shared_ptr.hpp>


namespace itgoggpatch
{

// Represents a kind of condition an Ogg Vorbis file's length must meet in order to be processed
struct PatcherLengthCondition
{
	enum Value
	{
		None, // Always process the file
		Equal, // Process the file if its length is equal to some length
		Greater // Process the file if its length is greater than some length
	};
};

class PatcherOptions
{
private:
	bool m_displayHelp;
	bool m_displayVersion;
	bool m_interactive;
	bool m_patchToRealLength;
	double m_timeInSeconds;
	PatcherLengthCondition::Value m_lengthConditionType; // The condition type to use when deciding whether to process a file
	double m_lengthCondition; // The number of seconds corresponding to the condition
	std::vector<lhcutils::StringPtr> m_startingPaths;

	// Get the command-line options object to use for processing command-line args
	//boost::program_options::options_description GetCmdOptions() const;
	
	// Get the command-line options object to use for displaying program usage
	//boost::program_options::options_description GetCmdOptionsForHelp() const;

public:
	//// Constructs default patcher options - patch to 105 seconds
	//// Might throw boost::system::system_error if the starting CWD couldn't be determined
	//PatcherOptions() : m_displayHelp(false), m_displayVersion(false), m_interactive(true),
	//	m_patchToRealLength(false), m_timeInSeconds(105), m_lengthConditionType(condition_none),
	//	m_lengthCondition(120), m_startingPaths(1, boost::filesystem::initial_path().file_string())
	//{
	//}

	// Constructs patcher options from command-line arguments
	PatcherOptions(const lhcutils::StartupEnvironment& args);
	
	// Prints program usage information to the given output stream, and given what name to use for this program.
	void PrintHelp(lhcutils::ITextWriter& output) const;
	// Gets or sets the DisplayHelp property - whether the program should display usage information.
	void SetShouldDisplayHelp(bool displayHelp) { m_displayHelp = displayHelp; }
	bool ShouldDisplayHelp() const { return m_displayHelp; }
	// Prints program version information to the given output stream
	void PrintVersion(lhcutils::ITextWriter& output) const;
	// Gets or sets the DisplayVersion property - whether the program should display version information
	void SetShouldDisplayVersion(bool displayVersion) { m_displayVersion = displayVersion; }
	bool ShouldDisplayVersion() const { return m_displayVersion; }
	// Gets or sets the Interactive property - if false, the program should not ask for user input
	void SetIsInteractive(bool interactive) { m_interactive = interactive; }
	bool IsInteractive() const { return m_interactive; }
	// Set the option to patch to the song's real length
	void SetModePatchToRealLength() { m_patchToRealLength = true; }
	// Is the option set to patch to the song's real length?
	bool PatchingToRealLength() const { return m_patchToRealLength; }
	// Set the time in seconds to patch files to
	void SetTimeInSecondsToPatchTo(double timeInSeconds) { m_patchToRealLength = false; m_timeInSeconds = timeInSeconds; }
	// Gets the time in seconds to patch files to or -1 if patching to real length
	double GetTimeInSecondsToPatchTo() const { return !m_patchToRealLength ? m_timeInSeconds : -1; }
	
	// These methods force clients to use a std::vector<std::string>.
	// C++ doesn't have interface classes for its standard library containers like C# does. :(

	// Sets the paths to patch
	void SetStartingPaths(const std::vector<lhcutils::StringPtr>& startingPaths) { m_startingPaths = startingPaths; }
	// Gets the paths to patch
	const std::vector<lhcutils::StringPtr>& GetStartingPaths() const { return m_startingPaths; }
	// Gets the paths to patch, allowing modification
	//std::vector<std::string>& StartingPaths() { return m_startingPaths; }
	
	// Only process files with length equal to the given number of seconds. Only one condition may be used.
	void UseLengthEqualCondition(double lengthCondition)
	{
		m_lengthConditionType = condition_equal;
		m_lengthCondition = lengthCondition;
	}
	// Only process files with length greater than the given number of seconds. Only one condition may be used.
	void UseLengthGreaterThanCondition(double lengthCondition)
	{
		m_lengthConditionType = condition_greater;
		m_lengthCondition = lengthCondition;
	}
	// Process all files.
	void DontUseLengthCondition()
	{
		m_lengthConditionType = condition_none;
	}

	// Gets the length condition type in use
	PatcherLengthCondition::Value LengthConditionType() const { return m_lengthConditionType; }
	// Gets the number of seconds for the length condition. Only has meaning for conditions other than condition_none
	double GetSecondsOfLengthCondition() const { return m_lengthCondition; }

	// Returns true if a song with the given reported song length meets the conditions of this options object
	bool LengthMeetsConditions(double reportedSongLength) const;

	// Returns true if the given Ogg Vorbis file meets the conditions of this options object.
	// Throws: ogglength::OggVorbisException if the file is not a valid ogg vorbis file.
	// Throws: FileNotFoundException, IoException
	//bool FileMeetsConditions(const lhcutils::UnicodeString& file) const;
	
	// Throws: ogglength::OggVorbisException if the file is not a valid ogg vorbis file.
	// Throws: IoException
	bool FileMeetsConditions(lhcutils::IStream& oggStream) const;
};

}

#endif

/*
 Copyright 2011 Greg Najda

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
